perm filename FROM.SAI[SAI,LES] blob sn#836014 filedate 1987-03-09 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00005 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	begin "FROM"
C00004 00003				! date conversion
C00006 00004				! procedures
C00009 00005				! Execution
C00012 ENDMK
C⊗;
begin "FROM"
require "head" source_file;
!
Scans one or more message files containing at most one message per page,
extracts the return address from the "From:" line of each message,
separates the host name from the user ID, and outputs a text file
containing one line per input message in the form
<host> <user ID> <file number>
where <file number> is the integer number of files that have been read,
beginning with 1.  The last line of the output file will be a list of the
files read:
 <1st file name> <2nd file name> <3rd file name> <etc.>

1987 Feb. 19: First version written by Les Earnest for SU-bboards census.
;

break(inlineups,LF&FF,CR,"IKNS");	! read a line upper-casified;
scnbrk(tolbroks,"<","","IS");		! scan to "<";
scnbrk(torbroks,">","","IS");		! scan to ">";
scnbrk(toats,"@","","IS");		! scan to "@";
scnbrk(tosemis,":","","IS");		! scan to ":";
scnbrk(tobangs,"!","","IS");		! scan to "!";
scnbrk(topers,"%","","IS");		! scan to "%";
scnbrk(todsss," -/","","IS");		! scan to " -/";
			! date conversion;

boolean proc equiv(STRING A,B);  begin
! returns true if A is identical to B[1 to length(A)], neglecting case shifts;
	WHILE LN(A) DO IF (LOP(A) LAND '137)≠(LOP(B) land '137) THEN RETURN(FALSE);
	RETURN(TRUE)
	END;

integer proc match(string m; string array ss; integer sstop);	begin
	integer mi,mp,ml;			! find unambiguous match between;
	mp←0;  if (ml←ln(m))=0 then return(0);	! m and one of ss;
	for mi←1 thru sstop do if equiv(m,ss[mi]) then
		if mp then return(-1) else mp←mi;
	return(mp)
	end "MATCH";
	
PRELOAD_WITH "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
	"JUL", "AUG", "SEP", "OCT", "NOV", "DEC";
STRING ARRAY MONTH[1:12];

integer procedure datint(string date);	begin
    ! converts date of form 08-Feb-87 to integer;
    integer da,mo;

    da←cvd(todsss(date));	! get day of month;
    return(if (mo←match(towhites(date),month,12))≤0 then 0 else
      (cvd(date)*12 + mo - 1)*31 + da -1);
    end;   
			! procedures;
integer pageno;		! count of pages;
integer fileno;		! sequential number of file;
string partial;		! last line beginning with "∂";

proc barf(string msg);  ! grumble;
    print("Page ",pageno,": ",msg,↓,partial,↓);

recursive procedure identify(string froms; boolean prim);   begin
    ! find id & host from "froms" if possible, else use "partial";
    procedure badfrom(string msg); begin
	barf(msg);
	print(froms,↓)
	end;
    string host,id;	! sender's host & identifier;
    string aline;
    string bang;

    aline←froms;
    host←tolbroks(aline);
    if brk = "<" then host←torbroks(aline) else begin "nobroket"
	aline←host[6 to ∞]; ! skip the "From:";
	toprintr(aline);
	host←towhites(aline);
	end "nobroket";
    if host="@" then tosemis(host);     ! strip off gateway;
    host←towhites(host);
			! now we should have id@host;
    bang←toats(host);
    id←tobangs(bang);
    while brk="!" do begin      ! translate UUCP into domain;
	host←id&">"&host;
	id←tobangs(bang);
	end;
    bang←topers(id);		! look for "%" form;
    if ln(id) then host←id&"%"&host;
    if ln(host)=0 then begin
	if prim then identify(partial,false) else badfrom("No host")
	end
      else if ln(bang)=0 then barf("No user id")
      else cprint(ouch,host," ",bang," ",fileno,↓);
    end "IDENTIFY";

procedure sailid;	begin		! output SAIL identifier;
    string aline,id;
    towhites(aline←partial);   ! flush date;
    toprintr(aline);           ! skip spaces;
    towhites(aline);           ! skip time;
    toprintr(aline);           ! skip spaces;
    id←towhites(aline);        ! get id;
    if 1<ln(id)≤3 then cprint(ouch,"SAIL.STANFORD.EDU ",id," ",fileno,↓)
      else identify(id,false);
    end;
			! Execution;
string filist;
integer begday,enday;

enton(ask("Finds where and who mail came from.
Output file="));
if (begday←datint(ask("Starting date (e.g. 06-FEB-87) or null: ")))≤0 then
  outstr("No date constraint"&↓)
  else while (enday←datint(ask("End date: ")))≤0 do outstr("Eh?"&↓);

fileno←0;
filist←"";
while true do begin "main"
    string ifile, aline;
    boolean fl;

    do begin "read"
	release (inch);
	if ln(ifile←ask("Mail file=")) = 0 then done "main";
	open(inch←getchan,"DSK",1,19,0,400,brk,eof);
	lookup(inch,ifile,fl);
	end "read"
      until ¬fl;

    filist←filist&" "&ifile;
    fileno←fileno + 1;
    pageno←0;

! might be better to look for "∂", "From" & "sender" and take the best one;

    do begin "file"
	boolean fromseen;
	pageno←pageno + 1;
	fromseen←false;
	partial←"";
	do begin "page"
	    integer day;
	    aline←input(inch,inlineups);
	    if aline="∂" ∧ (begday≤0 ∨ 
	      ((day←datint(aline[2 to 10])) ≥ begday) ∧ (day ≤ enday))
	      then begin "partial"
		if ln(partial) ∧ ¬fromseen then sailid;
		partial←aline;
		fromseen←false;
		end
	      else if equ(aline[1 to 5],"FROM:") ∧ ln(partial) ∧ ¬fromseen
	      then begin "from"
		fromseen←true;
		identify(aline,true);
		end "from"
	    end "page"
	  until brk=ff ∨ eof;
	if ln(partial) ∧ ¬fromseen then sailid;
	end "file"
      until eof;
    end "main";
    cprint(ouch,filist,↓);
    exit;
end